package com.xiashitech.agent.instrumentation.db.statement;

import com.xiashitech.agent.instrumentation.db.statement.sanitizer.impl.XSSqlSanitizer;
import io.opentelemetry.javaagent.shaded.instrumentation.api.db.SqlStatementInfo;
import io.opentelemetry.javaagent.shaded.instrumentation.api.instrumenter.SpanNameExtractor;
import io.opentelemetry.javaagent.shaded.instrumentation.api.instrumenter.db.SqlClientAttributesGetter;

public class XSJdbcSpanNameExtractor<DbRequest> implements SpanNameExtractor<DbRequest> {
    private final SqlClientAttributesGetter<DbRequest> getter;
    private static final XSSqlSanitizer sanitizer = new XSSqlSanitizer();
    private static final String DEFAULT_SPAN_NAME = "XS.DB";
    private XSJdbcSpanNameExtractor(SqlClientAttributesGetter<DbRequest> getter) {
        this.getter = getter;
    }
    public static <DbRequest> SpanNameExtractor<DbRequest> create(
            SqlClientAttributesGetter<DbRequest> getter) {
        return new XSJdbcSpanNameExtractor(getter);
    }
    @Override
    public String extract(DbRequest dbRequest) {
        //TODO UPDATE otel 1.29.0; TO DELETE on Next Version
        //String dbName = getter.name(dbRequest);
        //SqlStatementInfo sanitizedStatement = sanitizer.sanitize(getter.rawStatement(dbRequest));
        //return computeSpanName(dbName, sanitizedStatement.getOperation(), sanitizedStatement.getTable());
        SqlStatementInfo sanitizedStatement = sanitizer.sanitize(getter.getRawStatement(dbRequest));
        String dbName = getter.getName(dbRequest);
        return computeSpanName(dbName, sanitizedStatement.getOperation(), sanitizedStatement.getMainIdentifier());
    }
    private String computeSpanName(String dbName, String operation, String table) {
        if (operation == null) {
            return dbName == null ? DEFAULT_SPAN_NAME : DEFAULT_SPAN_NAME + "." + dbName;
        }

        StringBuilder name = new StringBuilder(operation);
        if (dbName != null || table != null) {
            name.append(' ');
        }
        // skip db name if table already has a db name prefixed to it
        if (dbName != null && (table == null || table.indexOf('.') == -1)) {
            name.append(dbName);
            if (table != null) {
                name.append('.');
            }
        }
        if (table != null) {
            name.append(table);
        }
        return DEFAULT_SPAN_NAME + "." + name.toString();
    }
}
